
#define NDEBUG false

#include "application.h"
#include "zpr.h"

#include <GL/glut.h>

Application* application;
bool isTranslation = false;

int winw = 600, winh = 600;

using namespace std;

/// OpenGL display function
void display() {
   application->draw();

   glDisable(GL_LIGHTING);
   //application->renderInfo(isTranslation);
   glEnable(GL_LIGHTING);

   glutSwapBuffers();
}

void idle() {
   glutPostRedisplay();
}

/// OpenGL reshape function
void reshape(int w, int h) {
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glOrtho(-1.2, 1.2, -1.2, 1.2, -4, 4);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   winw = w;
   winh = h;
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glutPostRedisplay();
}

/// OpenGL key press function
void keypress(unsigned char key, int x, int y) {
   switch (key) {
      case 27: {
         exit(0);
      }
      case 'n': {
         application->invertDrawN();
         break;
      }
      case '+': {
         application->getCursor()->in();
         break;
      }
      case '-': {
         application->getCursor()->out();
         break;
      }
      case '.': {
         application->getCursor()->increase();
         break;
      }
      case ',': {
         application->getCursor()->decrease();
         break;
      }
      case 't': {
         isTranslation = !isTranslation;
         break;
      }
      case 'q': {
         application->alternShowInterface();
         break;
      }
      case 's': {
	     application->invertDrawP();
	     break;
	  }
      case 'a': {
    	 application->showAtlas();
         break;
      }
      case 'z': {
         application->yDrawB();
         break;
      }
      case 'x': {
         application->nDrawB();
         break;
      }
      case 'b': {
         application->invDrawCB();
         break;
      }
      case 'A': {
		 application->invertShowMapOnAtlas();
		 break;
      }
   }
   glutPostRedisplay();
}

void mouseclick(int button, int state, int x, int y) {
   if (state == GLUT_DOWN) {
      if (button == GLUT_LEFT_BUTTON) {
         application->mouseLeft(x, y);
      } else if (button == GLUT_MIDDLE_BUTTON) {
         application->mouseMiddle(x, y);
      } else if ((button == GLUT_RIGHT_BUTTON)) {
         application->mouseRight(x, y);
      }
   } else if (state == GLUT_UP) {
      application->mouseUp(x, y);
   }
   glutPostRedisplay();
}

/// Mouse move function
void mousemove(int x, int y) {
   application->updateMouseCoords(x, y);
   glutPostRedisplay();
}

/// Passive mouse move function
void passivemousemove(int x, int y) {
   application->getCursor()->updatePosition(x, winh - y);
   glutPostRedisplay();
}

/// Print error message and exit program
void printInfoAndExit() {
   cout << endl;
   cout << "Usage: gps filename.off" << endl;
   exit(0);
}

int main(int argc, char **argv) {
   // Glut setup
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
   glutInitWindowSize(winw, winh);
   glutInitWindowPosition(150, 0);
   glutCreateWindow("glut Paint Shape");

   if (argc != 2)
      printInfoAndExit();

   application = new Application(winh, winh);
   application->buildMesh(argv[1]);
   application->init();

   // Callbacks registration
   glutDisplayFunc(display);

   zprInit();
   zprSelectionFunc(display); /* Selection mode draw function */

//   glutReshapeFunc(reshape);
//   glutMouseFunc(mouseclick);
//   glutMotionFunc(mousemove);
   glutPassiveMotionFunc(passivemousemove);
   glutKeyboardFunc(keypress);
   glutIdleFunc(idle);
   //   glutTimerFunc(6, timer, 6);
   glutMainLoop();
   return 0;
}
